package com.wuage.application.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuage.application.IUacAccountService;
import com.wuage.application.IUacRoleService;
import com.wuage.domain.mapper.UacAccountMapper;
import com.wuage.domain.mapper.UacRoleMapper;
import com.wuage.domain.mapper.UacRolePermissionMapper;
import com.wuage.domain.mapper.UacTenantMapper;
import com.wuage.domain.model.UacAccount;
import com.wuage.domain.model.UacRole;
import com.wuage.domain.model.UacRolePermission;
import com.wuage.domain.model.UacTenant;
import com.wuage.infrastructure.exception.BizException;
import com.wuage.infrastructure.status.BizResultCode;
import com.wuage.infrastructure.status.RoleEnum;
import com.wuage.infrastructure.utils.BeanUtils;
import com.wuage.infrastructure.utils.JwtUtils;
import com.wuage.interfaces.role.domian.UacRoleDO;
import com.wuage.interfaces.role.domian.UacRolePageDO;
import com.wuage.interfaces.role.domian.UacRoleUpdateDO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * (UacRole)表服务实现类
 *
 * @Author: makejava
 * @Date: 2021-09-27 17:00:43
 */
@Service("uacRoleService")
public class UacRoleServiceImpl extends ServiceImpl<UacRoleMapper, UacRole> implements IUacRoleService {

    @Resource
    private UacRoleMapper uacRoleMapper;
    @Resource
    private UacTenantMapper uacTenantMapper;
    @Resource
    private UacRolePermissionMapper uacRolePermissionMapper;
    @Resource
    private UacAccountMapper uacAccountMapper;
    @Resource
    private IUacAccountService uacAccountService;

    private Long getTenantId() {
        return JwtUtils.getLoginUser().getTenantId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UacRole createAdmin(UacTenant uacTenant) {
        UacRole uacRole =
                UacRole.builder()
                        .roleName(uacTenant.getName() + "管理员")
                        .roleCode(RoleEnum.ADMIN.getRoleCode())
                        .description(uacTenant.getName() + "管理员")
                        .tenantId(uacTenant.getId())
                        .tenantName(uacTenant.getName())
                        .build();
        this.save(uacRole);
        return uacRole;
    }

    @Override
    public UacRole getByRoleAndTenant(String role, Long tenantId) {
        return this.lambdaQuery().eq(UacRole::getRoleCode, role).eq(!RoleEnum.SUPER_ADMIN.getRoleCode().equals(role), UacRole::getTenantId, tenantId).list().get(0);
    }

    @Override
    public Page<UacRole> getRoles(UacRolePageDO pageDO, Long tenantId) {
        return uacRoleMapper.selectPage(pageDO.page(), new QueryWrapper<UacRole>().lambda().eq(UacRole::getTenantId, tenantId)
                .like(StrUtil.isNotBlank(pageDO.getRoleName()), UacRole::getRoleName, pageDO.getRoleName()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addRole(UacRoleDO uacRoleDO) {
        Long tenantId = getTenantId();
        checkRoleCode(uacRoleDO.getRoleCode(), null, tenantId);
        UacTenant tenant = uacTenantMapper.selectById(tenantId);
        UacRole uacRole = BeanUtils.copyProperties(uacRoleDO, UacRole.class);
        uacRole.setTenantId(tenantId).setTenantName(Objects.isNull(tenant) ? null : tenant.getName());
        return this.save(uacRole);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRole(UacRoleUpdateDO uacRoleUpdateDO) {

        Long tenantId = getTenantId();
        checkRoleCode(uacRoleUpdateDO.getRoleCode(), uacRoleUpdateDO.getId(), tenantId);
        UacRole role = this.getById(uacRoleUpdateDO.getId());
        String roleCode = uacRoleUpdateDO.getRoleCode();
        if (StrUtil.isNotBlank(roleCode)) {
            uacAccountMapper.update(UacAccount.builder().role(roleCode).build(), new UpdateWrapper<UacAccount>().lambda().eq(UacAccount::getRole, role.getRoleCode()));
        }

        return this.update(BeanUtils.copyProperties(uacRoleUpdateDO, UacRole.class),
                new QueryWrapper<UacRole>().lambda().eq(UacRole::getTenantId, tenantId)
                        .eq(UacRole::getId, uacRoleUpdateDO.getId()));
    }

    /**
     * 校验角色编码是否合法
     *
     * @param roleCode 角色编码
     */
    private void checkRoleCode(String roleCode, Long roleId, Long tenantId) {
        //校验角色Code是否为Admin、SuperAdmin
        if (RoleEnum.ADMIN.getRoleCode().equals(roleCode) || RoleEnum.SUPER_ADMIN.getRoleCode().equals(roleCode)) {
            throw new BizException(BizResultCode.INVALID_ROLE_CODE);
        }
        //校验角色Code是否重复
        List<UacRole> list = this.lambdaQuery().eq(UacRole::getRoleCode, roleCode).eq(UacRole::getTenantId, tenantId).notIn(Objects.nonNull(roleId), UacRole::getId, roleId).list();
        if (CollectionUtil.isNotEmpty(list)) {
            throw new BizException(BizResultCode.ROLE_CODE_EXIST);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteRole(Long id) {
        Long tenantId = getTenantId();
        UacRole one = this.lambdaQuery().eq(UacRole::getId, id).eq(UacRole::getTenantId, tenantId).one();
        boolean flag = false;
        if (Objects.nonNull(one)) {
            flag = this.removeById(id);
            uacRolePermissionMapper.delete(new QueryWrapper<UacRolePermission>().lambda().eq(UacRolePermission::getRoleId, id));
            uacAccountMapper.update(UacAccount.builder().role("").build(), new UpdateWrapper<UacAccount>().lambda().eq(UacAccount::getRole, one.getRoleCode()));
        }
        return flag;
    }
}